<!-- Created by henian.xu on 2018/8/30. -->

<template>
    <div :class="['form-item feedback',{'feedback':isFeedback},{'success':isSuccess},{'error':isError},{'required':isRequired}]">
        <label
            class="header"
            :style="`width: ${labelWidth_};`">{{ label }}</label>
        <div
            class="body"
            :style="`margin-left: ${labelWidth_};`">
            <div class="content">
                <slot name="prepend">
                    <!--<div class="prepend">前置</div>-->
                </slot>
                <!--<div class="input">
                    <i class="f-icon before">&#xf058;</i>
                    <i class="f-icon after">&#xf058;</i>
                    <slot/>
                </div>-->
                <div :class="['cell',{'pa-l':$slots.prepend},{'pa-r':$slots.append}]">
                    <slot/>
                </div>
                <slot name="append">
                    <!--<div class="append">附加</div>-->
                </slot>
            </div>

            <div
                class="explain"
                v-if="validateMessage">{{ validateMessage }}</div>
        </div>
    </div>
</template>

<script>
import { Comm } from '~/utils';
import AsyncValidator from 'async-validator';
export default {
    name: 'FormItem',
    inject: ['xForm'],
    data() {
        return {
            validateState: '',
            validateMessage: '',
        };
    },
    props: {
        rules: {
            type: Object,
            default() {
                return null;
            },
        },
        prop: {
            type: String,
            default: '',
        },
        desc: {
            type: String,
            default: '',
        },
        label: {
            type: String,
            default: '',
        },
        feedback: {
            type: Boolean,
            default: false,
        },
        labelWidth: {
            type: String,
            default: '',
        },
    },
    computed: {
        formRules() {
            return Comm.getObjectValueByPath(this.xForm.rules, this.prop) || [];
        },
        fieldValue: {
            get() {
                const models = this.xForm.models;
                let path = this.prop;
                if (!models || !path) return;
                if (path.indexOf(':') !== -1) {
                    path = path.replace(/:/, '.');
                }
                return Comm.getObjectValueByPath(models, path);
            },
            cache: false,
        },
        mergeRules() {
            return [].concat(this.rules || this.formRules);
        },
        isRequired() {
            return !!this.mergeRules.find(item => item.required);
        },
        isValidating() {
            return this.validateState === 'validating';
        },
        isSuccess() {
            return this.validateState === 'success';
        },
        isError() {
            return this.validateState === 'error';
        },
        isFeedback() {
            return this.xForm.feedback || this.feedback;
        },
        labelWidth_() {
            const labelWidth = this.labelWidth || this.xForm.labelWidth;
            return isNaN(labelWidth) ? labelWidth : `${labelWidth}px`;
        },
    },
    watch: {
        fieldValue() {
            this.validate('change').catch(() => {
                /*只为了去除控制台多余的输出*/
            });
        },
    },
    methods: {
        filterRules(trigger) {
            return this.mergeRules
                .filter(rule => {
                    return !rule.trigger || rule.trigger.indexOf(trigger) !== -1;
                })
                .map(rule => ({ ...rule }));
        },
        validate(trigger) {
            let callback;
            const promise = new Promise((resolve, reject) => {
                callback = msg => {
                    msg ? reject(msg) : resolve(true);
                };
            });

            this.validateState = 'validating';
            const currRules = this.filterRules(trigger);
            const descriptor = {}; //An object declaring validation rules
            if (!currRules.length) {
                callback();
            } else {
                currRules.forEach(rule => {
                    delete rule.trigger;
                });
                descriptor[this.prop] = currRules;
                const validator = new AsyncValidator(descriptor);
                const model = {
                    [this.prop]: this.fieldValue,
                };
                validator.validate(model, { firstFields: true }, errors => {
                    this.validateState = !errors ? 'success' : 'error';
                    this.validateMessage = errors ? errors[0].message : '';
                    callback(this.validateMessage);
                });
            }
            return promise;
        },
        onError() {
            console.log(213123);
            this.$messageBox.tips(this.validateMessage);
        },
        clearValidate() {
            this.validateState = '';
            this.validateMessage = '';
            this.validateDisabled = false;
        },
    },
    created() {
        this.xForm.addField(this);
    },
    beforeDestroy() {
        this.xForm.removeField(this);
    },
};
</script>

<style lang="scss">
</style>
